----------------------------------------------------------------------------------
-- Company: Ensimag
-- Engineers: Muller, Viardot
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity PO is
Port (
CLK : in STD_LOGIC;
RST : in STD_LOGIC;

SelRa : in std_logic_vector(2 downto 0);
SelRb : in std_logic_vector(2 downto 0);
SelRd : in std_logic_vector(2 downto 0);
SelRin : in std_logic_vector(1 downto 0);
ERd : in STD_LOGIC;
EOUT : in STD_LOGIC;

CLRPC : in STD_LOGIC;
EPC : in STD_LOGIC;
LDPC : in STD_LOGIC;
SelPC : in STD_LOGIC;

selA : in STD_LOGIC;
selB : in STD_LOGIC;
ImmB : in STD_LOGIC_VECTOR(15 downto 0);

op : in std_logic_vector(5 downto 0);
ECarry : in STD_LOGIC;

EIR : in STD_LOGIC;
IR : out STD_LOGIC_VECTOR(15 downto 0);

selCond : in STD_LOGIC_VECTOR (2 downto 0);
cond : out STD_LOGIC;

ADPROG : out STD_LOGIC_VECTOR(15 downto 0);
DPROG : in STD_LOGIC_VECTOR(15 downto 0);

ADDATA : out STD_LOGIC_VECTOR(15 downto 0);
DDATAIN : in STD_LOGIC_VECTOR(15 downto 0);
DDATAOUT : out STD_LOGIC_VECTOR(15 downto 0);

PIN : in STD_LOGIC_VECTOR(3 downto 0);
POUT : out STD_LOGIC_VECTOR(7 downto 0)
);
end PO;

architecture RTL of PO is

type RegsType is array (natural range 0 to 7) of std_logic_vector(15 downto 0);

-- Registres PO
signal sPC : std_logic_vector(15 downto 0);
signal R : RegsType;

-- Chemin de donnee PO
signal Rin,PCin,Rd,Ra,Rb,RaUal,RbUal,sUAL : std_logic_vector(15 downto 0);
-- Carry
signal cin, cout : std_logic;

component UAL
port (
A : in std_logic_vector(15 downto 0);
B : in std_logic_vector(15 downto 0);
op : in std_logic_vector(5 downto 0);
CIN : in std_logic;
S : out std_logic_vector(15 downto 0);
COUT : out std_logic
);
end component;
component geneCond
port (
selCond : in STD_LOGIC_VECTOR (2 downto 0);
Ra : in STD_LOGIC_VECTOR (15 downto 0);
cond : out STD_LOGIC
);
end component;

begin


ADPROG<=sPC;
ADDATA <= sUAL;



RegPC: process (CLK,CLRPC,RST)
begin
if (CLRPC or RST) ='1' then
sPC<=(others => '0');
elsif (CLK'EVENT and CLK='1') then
if EPC='1' then
if LDPC='1' then
if SelPC='0' then
sPC <= unsigned(sUAL)-1;
else
sPC <= Rb;
end if;
else
sPC<=sPC+1;
end if;
end if;
end if;
end process RegPC;


RegIR: process (CLK)
begin
if (CLK'EVENT and CLK='1') then
     			if RST ='1' then 
      				IR <=(others => '0');
     			else
       				if (EIR='1') then
					IR<=DPROG;
      				end if;
     			end if;
end if;
end process RegIR;



C_SelRin: process(sUAL,DDATAIN,sPC,PIN,SelRIN)
begin
case SelRIN is
when "00" => RIN<=sUAL;
when "01" => RIN<=DDATAIN;
when "10" => RIN<=sPC;
when others => RIN <= "000000000000" & PIN;
end case;
end process C_SelRin;


Registres: process (CLK)
begin
if (CLK'EVENT and CLK='1') then
	if RST='1'  then
		for i  in R'range loop
			R(i) <= (others => '0');
		end loop;  -- i 
	else
		if Erd='1' then 
			R(conv_integer(SelRd))<=Rin;
		end if;
	end if;
end if;
end process Registres;


process (R,SelRb)
begin
Rb<=R(conv_integer(SelRb));
end process;

process (R,SelRa)
begin
Ra<=R(conv_integer(SelRa));
end process;

C_SelRa: process(SelA,sPC,Ra)
begin
if(SelA='0') then
RaUAL<=sPC;
else
RaUAL<=Ra;
end if;
end process C_SelRa;


C_SelRb: process(SelB,ImmB,Rb)
begin
if(SelB='0') then
RbUAL<=ImmB;
ELSE
RbUAL<=Rb;
end if;
end process C_SelRb;

RegOut : process (CLK)
begin
if (CLK'EVENT and CLK='1') then
if (EOUT='1') then
POUT<=Rb(7 downto 0);
end if;
end if;
end process RegOut;


Carry : process (CLK, RST)
begin
		if (CLK'EVENT and CLK='1') then
			if RST='1' then
				cin <= '0';
			else
				if ECarry='1' then
					cin <= cout;
				end if;
			end if;
		end if;
end process Carry;

-- Bus DDATAOUT
C_DDATAOUT: process(R,SelRd)
begin
case SelRd is
when "000" => DDATAOUT<=R(0);
when "001" => DDATAOUT<=R(1);
when "010" => DDATAOUT<=R(2);
when "011" => DDATAOUT<=R(3);
when "100" => DDATAOUT<=R(4);
when "101" => DDATAOUT<=R(5);
when "110" => DDATAOUT<=R(6);
when others => DDATAOUT <= R(7);
end case;
end process C_DDATAOUT;

C_UAL : UAL
port map ( A => RaUAL ,B=> RbUAL, op => op, CIN=> cin, S=>sUAL, COUT => cout);

C_geneCond : geneCond
port map ( selCond => selCond ,Ra=> Ra, cond => cond);



end RTL;